package ru.padre386.geo_utils.data_loaders.gpx;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import ru.padre386.geo_utils.data_loaders.common.ITrackContainer;
import ru.padre386.geo_utils.data_loaders.common.ITracksLoader;
import ru.padre386.geo_utils.data_loaders.gpx.domain.GpxFile;
import ru.padre386.geo_utils.data_loaders.gpx.domain.GpxPoint;
import ru.padre386.geo_utils.data_loaders.gpx.domain.GpxSegment;
import ru.padre386.geo_utils.data_loaders.gpx.domain.GpxTrack;

import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.TimeZone;

/**
 * Created by IntelliJ IDEA.
 * User: indrdb
 * Date: 04.02.2011
 * Time: 14:27:34
 */
public class GpxLoader implements ITracksLoader {
    private SimpleDateFormat dateFormat;

    public GpxLoader() {
        dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        dateFormat.setTimeZone(TimeZone.getTimeZone("Z"));
    }

    private SAXBuilder initBuilder() {
        SAXBuilder builder = new SAXBuilder();
        builder.setValidation(false);
        return builder;
    }

    @Override
    public ITrackContainer load(InputStream stream) {
        SAXBuilder builder = initBuilder();

        Document document;
        try {
            document = builder.build(stream);
        } catch (JDOMException e) {
            throw new IllegalStateException(e);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }

        return parse(document);
    }

    private GpxFile parse(Document document) {
        Element root = document.getRootElement();
        @SuppressWarnings({"unchecked"}) List<Element> listTrks = root.getChildren("trk", null);

        final GpxFile gpxFile = new GpxFile();
        for (Element tmpTrk : listTrks) {
            final GpxTrack gTrack = new GpxTrack();
            final Element name = tmpTrk.getChild("name", null);
            if (name != null) {
                gTrack.setName(name.getValue());
            }

            @SuppressWarnings({"unchecked"}) List<Element> segments = tmpTrk.getChildren("trkseg", null);
            if (segments != null) {
                for (Element segment : segments) {
                    final GpxSegment gSegment = new GpxSegment();
                    @SuppressWarnings({"unchecked"}) final List<Element> points = segment.getChildren("trkpt", null);

                    if (points != null) {
                        for (Element point : points) {
                            final GpxPoint gPoint = new GpxPoint();
                            gPoint.setLat(Double.valueOf(point.getAttributeValue("lat")));
                            gPoint.setLon(Double.valueOf(point.getAttributeValue("lon")));
                            final Element ele = point.getChild("ele", null);
                            if (ele != null) {
                                gPoint.setEle(Double.valueOf(ele.getValue()));
                            }
                            final Element time = point.getChild("time", null);
                            if (time != null) {
                                try {
                                    gPoint.setTime(dateFormat.parse(time.getValue()));
                                } catch (ParseException e) {
                                    e.printStackTrace();
                                }
                            }
                            gSegment.addPoint(gPoint);
                        }
                    }
                    gTrack.addSegment(gSegment);
                }
            }
            gpxFile.addTrack(gTrack);
        }
        return gpxFile;
    }
}
